package postgres

import (
	"context"
	"gorm.io/gorm"
	"manager/model"
	"manager/model/entity"
)

var Store = &store{}

type store struct{}

func (a *store) Create(ctx context.Context, m *entity.Store) (int64, error) {
	err := dbWithContext(ctx).Create(m).Error
	return m.ID, err
}
func (a *store) ExecTx(ctx context.Context, fn func(ctx context.Context) error) error {
	return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		ctx = context.WithValue(ctx, contextTxKey{}, tx)
		return fn(ctx)
	})
}

func (a *store) Find(ctx context.Context, id int64) (*entity.Store, error) {
	e := &entity.Store{}
	err := dbWithContext(ctx).Model(&entity.Store{}).First(&e, id).Error
	return e, err
}

func (a *store) Update(ctx context.Context, id int64, dict map[string]interface{}) error {
	return dbWithContext(ctx).Model(&entity.Store{}).Where("id = ?", id).Updates(dict).Error
}

func (a *store) Delete(ctx context.Context, id int64) error {
	return dbWithContext(ctx).Delete(&entity.Store{}, id).Error
}

func (a *store) List(ctx context.Context, in *model.StoreListRequest) (int, []*entity.Store, error) {
	var (
		q      = dbWithContext(ctx).Model(&entity.Store{})
		err    error
		total  int64
		stores []*entity.Store
	)

	if in.Id > 0 {
		q = q.Where("id = ?", in.Id)
	}

	if in.Status != nil {
		q = q.Where("status = ?", *in.Status)
	}
	if in.Name != nil {
		q = q.Where("name like ?", "%"+*in.Name+"%")
	}
	if in.Phone != nil {
		q = q.Where("phone like ?", "%"+*in.Phone+"%")
	}
	if in.AreaID != nil {
		q = q.Where("area_id = ?", *in.AreaID)
	}

	if in.CountryCode != nil {
		q = q.Where("country_code = ?", *in.CountryCode)
	}

	if in.ProvinceCode != nil {
		q = q.Where("province_code = ?", *in.ProvinceCode)
	}

	if in.CityCode != nil {
		q = q.Where("city_code = ?", *in.CityCode)
	}

	if in.ZoneCode != nil {
		q = q.Where("zone_code = ?", *in.ZoneCode)
	}

	if err = q.Count(&total).Error; err != nil {
		return 0, nil, err
	}

	if in.Ids != nil && len(in.Ids) > 0 {
		q = q.Where("id in ?", in.Ids)
		if err = q.Scan(&stores).Error; err != nil {
			return 0, nil, err
		}
		return int(total), stores, nil
	}

	if err = q.Order("id asc").Limit(in.Size).Offset((in.Index - 1) * in.Size).Scan(&stores).Error; err != nil {
		return 0, nil, err
	}
	return int(total), stores, nil
}

func (a *store) CountByArea(ctx context.Context, areaIds []int64) ([]*model.CountByAreaResponse, error) {
	var (
		err                 error
		q                   = db.WithContext(ctx).Model(&entity.Store{})
		countByAreaResponse = make([]*model.CountByAreaResponse, 0)
	)
	err = q.Select("area_id", "count(*) as count").Where("area_id in ?", areaIds).Group("area_id").Scan(&countByAreaResponse).Error
	return countByAreaResponse, err

}
